package com.swipemaster.elements;

import android.graphics.Canvas;

import com.swipemaster.common.Global;
import com.swipemaster.moves.NoMove;
import com.swipemaster.moves.PathMove;

/** Snake is a sequential container for elements. */
public class Snake extends Element
{
	/** Number of elements in snake. */
	protected int elementsCounter = 0;
	/** Maximum number of elements per snake. */
	public static final int MAX_SNAKE_ELEMENTS = 15;
	/** Elements in snake. */
	protected Element[] elements = new Element[MAX_SNAKE_ELEMENTS];
	/** Snake's target. */
	protected int[] target = new int[2];

	/** @param length Length of snake. */
	public Snake(int length)
	{
		super(0, 0, new NoMove(), 0);
		if (length > MAX_SNAKE_ELEMENTS)
		{
			throw new IllegalArgumentException("Exceeded maximal number of elements per snake");
		}
	}

	/** Adds snake element. */
	public void addSnakeElement(Element element)
	{
		if (elementsCounter >= MAX_SNAKE_ELEMENTS)
		{
			throw new IllegalArgumentException("Exceeded maximal number of elements per snake");
		}
		if ((element.move instanceof PathMove) == false)
		{
			throw new IllegalArgumentException("Snake elements can move only with PathMove");
		}

		elements[elementsCounter++] = element;
		setTarget();
		setPaths();
	}

	@Override
	public void draw(Canvas canvas)
	{
		for (int i = 0; i < elementsCounter; i++)
		{
			elements[i].draw(canvas);
		}
	}

	@Override
	public boolean isCollisionWith(Element element)
	{
		for (int i = 0; i < elementsCounter; i++)
		{
			if (elements[i].isCollisionWith(element))
			{
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean isWallCollision(int direction, boolean wallCollision)
	{
		return false;
	}

	@Override
	public void move(int interval)
	{
		for (int i = 0; i < elementsCounter; i++)
		{
			elements[i].move(interval);
		}

		// if head element reached his target
		if (((PathMove) elements[0].move).reached)
		{
			setTarget();
			changePaths();
		}
	}

	@Override
	public void speedUp(double scale)
	{
		for (int i = 0; i < elementsCounter; i++)
		{
			elements[i].speedUp(scale);
		}
	}

	/** Adjusts paths of elements after reaching another target by snake */
	protected void changePaths()
	{
		((PathMove) elements[0].move).setTargets(target);
		for (int i = 1; i < elementsCounter; i++)
		{
			((PathMove) elements[i].move).appendTarget(target);
		}
	}

	/** Sets paths of elements' moves before start of game. */
	protected void setPaths()
	{
		((PathMove) elements[0].move).setTargets(target);
		for (int i = 1; i < elementsCounter; i++)
		{
			final int[] targets =
			{ elements[0].x, elements[0].y };
			((PathMove) elements[i].move).setTargets(targets);
			((PathMove) elements[i].move).appendTarget(target);
		}
	}

	protected void setTarget()
	{
		target[0] = (int) (Math.random() * Global.app.consts.width);
		target[1] = (int) (Math.random() * Global.app.consts.height);
	}
}
